/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package multi.agent.simulation;

import jade.core.AID;
import jade.core.Agent;
import jade.core.behaviours.TickerBehaviour;
import jade.domain.DFService;
import jade.domain.FIPAAgentManagement.*;
import jade.domain.FIPAException;
import jade.lang.acl.ACLMessage;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import multi.agent.simulation.behaviour.TrafficRequest;
import multi.agent.simulation.listeners.InformListener;

/**
 *
 * @author Mauro Perez
 */
public class TrafficAgent extends Agent
{
    public MessageRequest MsgRequest;
    public ArrayList<LinkInfo> Links;
    public int ResponceCounter = 0;
    public String _agentName;
    public int _dbID;
    private Object[] _args;
    private int _movingAgentsCount = 0;
    private final String _language = "English";
    private final String _ontology = "traffic-ontology";   



    
    /*
     * Agent setup. This performs agent initialization, e.g. load variables or required values.
     */
    @Override
    protected void setup() 
    {
        MsgRequest = new MessageRequest();
                
        _agentName = getAID().getLocalName(); 
        _args = getArguments();
        _dbID = Integer.parseInt(_args[0].toString());
        
        /*_args = getArguments();
        Links = new ArrayList<LinkInfo>();
        Links.add(new LinkInfo(_args));*/
        
        System.out.println("Traffic agent: " + _agentName + " initialized, Linked to Traffic agent: ");
        
        RegisterToDirectory();
        DisplayDirectory();
            
        //Add behaviours
        InitBehavoirs();
        
        System.out.println("Traffic agent:" + _agentName + " initialized");
        super.setup();
    }
        
    private void RegisterToDirectory()
    {
        ServiceDescription sd  = new ServiceDescription();
        sd.setType( "node" );
        sd.setName( getLocalName() );
        
        DFAgentDescription dfd = new DFAgentDescription();
        dfd.setName(getAID());
        dfd.addServices(sd);

        try 
        {  
            DFService.register(this, dfd );  
            System.out.println("Traffic agent:" + _agentName + " Register in DF");
        }
        catch (FIPAException fe) { fe.printStackTrace(); }
    }
    
    private void DisplayDirectory()
    {
        DFAgentDescription dfd = new DFAgentDescription();
        DFAgentDescription[] result;
        try 
        {
            result = DFService.search(this, dfd);
            System.out.println("Search returns: " + result.length + " elements" );
            if (result.length>0)
            {
                    System.out.println(" " + result[0].getName() );
            }
        }
        catch (FIPAException ex) 
        {
            Logger.getLogger(TrafficAgent.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
   
    

    @Override
    protected void takeDown() {
        //Clean up agent resurces        
        super.takeDown();
    }    
    
    private void InitBehavoirs() 
    {
        //Prints the count of agents currently on this node.
        /*addBehaviour(new TickerBehaviour(TrafficAgent.this, 5000) {
            @Override
            protected void onTick() {
                System.out.println(_agentName + " current contains " + _movingAgentsCount + " moving agents");
            }
        });*/
        
        //Create the traffic behaviour
        TrafficRequest request = new TrafficRequest(this);
        request.setInformListener(new InformListener() 
        {
            @Override
            public void onInform() 
            {
                //_movingAgentsCount++;
                // for each reponce recived the 
                ResponceCounter = ResponceCounter -1;
                
                if(ResponceCounter == 0)
                {
                    //All message where received this mean that you 
                    // could send message back to node related.

                ACLMessage msg = new ACLMessage(ACLMessage.INFORM); 
                msg.addReceiver(new AID(MsgRequest.EndNode, false));
                msg.setLanguage(_language);
                msg.setOntology(_ontology);
                msg.setContent(SelectBetterRoute());
                send(msg);
                
                }
            }
        });
        addBehaviour(request);
    }
    
    private String SelectBetterRoute()
    {
         //string representation of responce RequestID;OverHead;LinkSequence
        
        String retval = "";
        int MinOverHeadValue = 100;
        String Route = "";
        
        Iterator it = this.MsgRequest.responceList.iterator();
        while(it.hasNext())
        {
            MessageResponce responce = (MessageResponce)it.next();
            if (responce.OverHead < MinOverHeadValue) 
            {
                MinOverHeadValue = responce.OverHead;
                Route = responce.LinkSequence;
            }

        }
        
        //Find a way to add this link overhead.
        retval = this.MsgRequest.Id + ";" + MinOverHeadValue + ";" + Route;
       
        return retval;
    }
}
